﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Dynamic.Core;
using Microsoft.EntityFrameworkCore;
using PMS.SANY.Entity;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using PMS.SANY.MonOrderServer.Enums;

namespace PMS.SANY.MonOrderServer
{
    public partial class WorkStation
    {
        /// <summary>
        /// 获取下一个待下发的【订单工序】
        /// </summary>
        /// <returns></returns>
        public async Task<OprSequence> GetNextSequenceAsync()
        {
            OprSequence result = null;
            using (var db = new GDbContextFactory().DbContext())
            {
                try
                {
                    var list = await db.Plan
                        .Where(p => p.Deleted == false && p.Status == PlanStatus.Execute)
                        .OrderBy(o => o.IssuedTime)
                        .ToListAsync();

                    if (list == null || list.Count == 0) return null;//当前无可执行的计划

                    for (var idx = 0; idx < list.Count; idx++)
                    {//按【下发时间】顺序，逐个匹配【待下发的工序】
                        var plan = list[idx];
                        //按指定工位抢订单
                        //var seq = await db.OprSequence
                        //    .Include(i => i.Plan)
                        //    .Where(p => p.PlanId == plan.Id && p.WorkStation == Id && p.ActQuantity < p.Quantity)
                        //    .FirstOrDefaultAsync();

                        if (await PreSequenceCompnayAsync(plan.WipOrderNo))
                        {
                            //恢复订单
                            var seq = await db.OprSequence
                                .Include(i => i.Plan)
                                .Where(p => p.PlanId == plan.Id && p.paramRsrv4 == Id && p.ActQuantity < p.Quantity)
                                .FirstOrDefaultAsync();

                            if (seq == null)
                            {
                                //按工序抢订单
                                seq = await db.OprSequence
                                    .Include(i => i.Plan)
                                    .Where(p => p.PlanId == plan.Id
                                        && (AlternateId.Contains(p.WorkStation) || p.WorkStation == Id)
                                        && (p.paramRsrv4 == null || p.paramRsrv4 == "" || p.paramRsrv4 == string.Empty)
                                        && p.ActQuantity < p.Quantity)
                                    .FirstOrDefaultAsync();
                            }

                            if (seq != null)
                            {
                                if (Parent.LockedOprSeq.TryAdd(seq.Id, true))
                                {
                                    //按【计划数量】与【实际完成数量】，来判断当前工序【是否已完成】
                                    if (await ModifyParam4Async(seq.Id, this.Id))
                                    {
                                        var psr = SetResultData(db, seq);

                                        bool value;
                                        Parent.LockedOprSeq.TryRemove(seq.Id, out value);
                                        return psr;
                                    }
                                    else
                                    {
                                        bool value;
                                        Parent.LockedOprSeq.TryRemove(seq.Id, out value);
                                        _logger.LogTrace("工位【" + Name + "】锁定订单【" + plan.Id + "】失败，修改Param4失败。");
                                    }
                                }
                                else
                                {
                                    _logger.LogTrace("工位【" + Name + "】锁定订单【" + plan.Id + "】失败");
                                }
                            }
                            else
                            {
                                _logger.LogTrace("工位【" + Name + "】数据库中未取到合适的订单");
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError("GetNextSequenceAsync Error:" + ex.Message);
                }
            }

            return result;
        }

        private OprSequence SetResultData(GDbContext db, OprSequence seq)
        {
            OprSequence result = seq;
            OprSequenceId = seq.Id;
            WipOrderNo = seq.Plan.WipOrderNo;
            ProductNo = seq.Plan.ProductNo;
            Quantity = Convert.ToInt32(seq.Quantity);
            ActQuantity = seq.ActQuantity;
            try
            {
                if (seq.Plan.SerialNo.Length > 2)
                {
                    SerialNo = JsonConvert.DeserializeObject<string[]>(seq.Plan.SerialNo);
                }
                else
                {
                    SerialNo = new string[0];
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
            }

            if (seq.ActQuantity > 0
                || seq.ProgressStatus == "130"
                || db.StationExecuted.Where(p => p.SequenceId == result.Id).Count() > 0)
            {//存在报工记录时，设置工位状态为生产中
                Status = Enums.WorkStationStatus.InProduction;
            }
            else
            {
                //获取到订单信息，可以下发了
                Status = WorkStationStatus.IsIssued;
            }

            return result;
        }

        /// <summary>
        /// 获取工序信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<OprSequence> GetSequenceAsync(string id)
        {
            using (var db = new GDbContextFactory().DbContext())
            {
                try
                {
                    return await db.OprSequence.Where(p => p.Deleted == false && p.Id == id).FirstOrDefaultAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError("GetSequenceAsync Error:" + ex.Message);
                    return null;
                }
            }
        }

        /// <summary>
        /// 获取工序信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> ModifySequenceAsync(string id, string status)
        {
            using (var db = new GDbContextFactory().DbContext())
            {
                try
                {
                    var entity = await db.OprSequence.Where(p => p.Deleted == false && p.Id == id).FirstOrDefaultAsync();
                    entity.ProgressStatus = status;
                    entity.ActQuantity = ActQuantity;
                    entity.ModifyTime = DateTime.Now;
                    db.Update(entity);
                    await db.SaveChangesAsync();
                    return true;
                }
                catch (Exception ex)
                {
                    _logger.LogError("ModifySequenceAsync Error:" + ex.Message);
                    return false;
                }
            }
        }

        public async Task<bool> ModifyParam4Async(string seqid, string paramRsrv4)
        {
            using (var db = new GDbContextFactory().DbContext())
            {
                try
                {
                    var entity = await db.OprSequence.Where(p => p.Deleted == false && p.Id == seqid).FirstOrDefaultAsync();
                    entity.paramRsrv4 = paramRsrv4;
                    db.Update(entity);
                    await db.SaveChangesAsync();
                    return true;
                }
                catch (Exception ex)
                {
                    _logger.LogError("ModifyParam4Async Error:" + ex.Message);
                    return false;
                }
            }
        }

        /// <summary>
        /// 检查待下发订单的上工序是否完成
        /// </summary>
        /// <returns></returns>
        public async Task<bool> PreSequenceCompnayAsync(string pid)
        {
            if (string.IsNullOrEmpty(PreOprSequenceNo)) return true;

            using (var db = new GDbContextFactory().DbContext())
            {
                try
                {
                    return await db.OprSequence.Where(p => p.PlanId == pid && p.OprSequenceNo == PreOprSequenceNo && p.ActQuantity > 0).CountAsync() > 0;
                }
                catch (Exception ex)
                {
                    _logger.LogError("PreSequenceCompnayAsync==>WipOrderNo=:" + WipOrderNo + "; PreOprSequenceNo=" + PreOprSequenceNo);
                    _logger.LogError("CheckPreSequenceAsync:" + ex.Message);
                    return true;
                }
            }
        }

        /// <summary>
        /// 获取订单信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<Plan> GetPlanAsync(string id)
        {
            using (var db = new GDbContextFactory().DbContext())
            {
                try
                {
                    return await db.Plan.Where(p => p.Deleted == false && p.Id == id).FirstOrDefaultAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError("GetPlanAsync Error:" + ex.Message);
                    return null;
                }
            }
        }

        /// <summary>
        /// 尝试办结订单
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task CheckPlanStatusAsync(string id)
        {
            if (IsLastSeq)
            {
                using (var db = new GDbContextFactory().DbContext())
                {
                    try
                    {
                        var entity = await db.Plan.Where(p => p.Deleted == false && p.Id == id).FirstOrDefaultAsync();
                        entity.Status = PlanStatus.Complete;
                        entity.ModifyTime = DateTime.Now;

                        db.Plan.Update(entity);
                        await db.SaveChangesAsync();
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError("CheckPlanStatusAsync Error:" + ex.Message);
                    }
                }
            }

            //using (var db = new GDbContextFactory().DbContext())
            //{
            //    try
            //    {
            //        if (sid == null || sid.Count == 0) sid = Siemens.WorkStationIds;

            //        var count = await db.OprSequence
            //               .Include(i => i.Plan)
            //               .Where(p => p.PlanId == WipOrderNo && p.ActQuantity < p.Quantity && sid.Contains(p.WorkStation))
            //               .CountAsync();

            //        if (count == 0)
            //        {
            //            var entity = await db.Plan.Where(p => p.Deleted == false && p.Id == id).FirstOrDefaultAsync();
            //            entity.Status = PlanStatus.Complete;
            //            entity.ModifyTime = DateTime.Now;

            //            db.Plan.Update(entity);
            //            await db.SaveChangesAsync();
            //        }

            //    }
            //    catch (Exception ex)
            //    {
            //        _logger.LogError("CheckPlanStatusAsync Error:" + ex.Message);
            //    }
            //}
        }

        /// <summary>
        /// 更新工序信息
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<int> SaveSequenceDataAsync(OprSequence entity)
        {
            using (var db = new GDbContextFactory().DbContext())
            {
                try
                {
                    entity.ModifyTime = DateTime.Now;
                    db.OprSequence.Update(entity);
                    return await db.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError("SaveSequenceDataAsync Error:" + ex.Message);
                    return 0;
                }
            }
        }

        /// <summary>
        /// 更新订单信息
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<int> SavePlanDataAsync(Plan entity)
        {
            using (var db = new GDbContextFactory().DbContext())
            {
                try
                {
                    entity.ModifyTime = DateTime.Now;
                    db.Plan.Update(entity);
                    return await db.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError("SavePlanDataAsync Error:" + ex.Message);
                    return 0;
                }
            }
        }

        public async Task AddStationExecuted(StationExecuted entity)
        {
            using (var db = new GDbContextFactory().DbContext())
            {
                try
                {
                    entity.ModifyTime = DateTime.Now;
                    await db.StationExecuted.AddAsync(entity);
                    await db.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError("AddStationExecuted Error:" + ex.Message);
                }
            }
        }
    }
}
